package com.example.services.impl;

import com.example.dtos.plugin.*;
import com.example.entities.Plugin;
import com.example.entities.PluginConfig;
import com.example.infrastructure.parser.PluginConfigExtract;
import com.example.infrastructure.parser.PluginConfigModel;
import com.example.repositories.PluginConfigMapper;
import com.example.repositories.PluginMapper;
import com.example.services.PluginService;
import com.example.common.dto.PageRequestDTO;
import com.example.common.dto.PaginationDTO;
import com.example.common.exception.BusinessException;
import com.example.common.ErrorCode;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.minio.*;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author moyin
 * @Description TODO
 * @Date 2025/3/20 11:38
 * @Email 82400672@qq.com
 **/
@Service
public class PluginServiceImpl implements PluginService {

    @Autowired
    private PluginMapper pluginMapper;
    @Autowired
    private PluginConfigMapper pluginConfigMapper;
    @Autowired
    private MinioClient minioClient;
    @Value("${minio.bucket-name}")
    private String bucketName;

    @Override
    public PaginationDTO<PluginListItemDTO> getPluginList(PageRequestDTO pageRequest, String status, String keyword) {
        // 构建查询条件
        LambdaQueryWrapper<Plugin> queryWrapper = new LambdaQueryWrapper<>();
        
        // 状态筛选
        if (!"all".equals(status)) {
            queryWrapper.eq(Plugin::getStatus, status);
        }
        
        // 关键词搜索
        if (StringUtils.hasText(keyword)) {
            queryWrapper.and(wrapper -> wrapper
                .like(Plugin::getId, keyword)
                .or()
                .like(Plugin::getName, keyword)
                .or()
                .like(Plugin::getDescription, keyword)
            );
        }
        
        // 执行分页查询
        Page<Plugin> page = new Page<>(pageRequest.getCurrentPage(), pageRequest.getPageSize());
        Page<Plugin> resultPage = pluginMapper.selectPage(page, queryWrapper);
        
        // 转换为DTO
        List<PluginListItemDTO> records = resultPage.getRecords().stream()
            .map(this::convertToListItemDTO)
            .collect(Collectors.toList());
        
        // 构建分页响应
        PaginationDTO<PluginListItemDTO> paginationDTO = new PaginationDTO<>();
        paginationDTO.setCurrentPage(pageRequest.getCurrentPage());
        paginationDTO.setPageSize(pageRequest.getPageSize());
        paginationDTO.setTotalRecords(resultPage.getTotal());
        paginationDTO.setRecords(records);  // 设置查询结果数据
        paginationDTO.calculateTotalPages();
        
        return paginationDTO;
    }
    
    /**
     * 将实体转换为列表项DTO
     */
    private PluginListItemDTO convertToListItemDTO(Plugin plugin) {
        return new PluginListItemDTO(
            plugin.getId(),
            plugin.getName(),
            plugin.getVersion(),
            null, // developer 暂不支持
            null, // email 暂不支持
            plugin.getStatus(),
            null, // installTime 暂不支持
            null, // updateTime 暂不支持
            plugin.getSinceBuild() + "-" + plugin.getUntilBuild(),
            plugin.getDescription()
        );
    }

    @SneakyThrows
    @Override
    public PluginUploadResponseDTO uploadPlugin(MultipartFile file, boolean autoActivate) {
        List<PluginConfigModel> pluginConfigs = PluginConfigExtract.extract(file);

        // 检查存储桶是否存在
        boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder()
                .bucket(bucketName).build());
        if (!isExist) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }

        // 上传文件
        ObjectWriteResponse objectWriteResponse = minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(file.getOriginalFilename())
                        .stream(file.getInputStream(), file.getSize(), -1)
                        .contentType(file.getContentType())
                        .build()
        );

        PluginConfigModel pluginConfigModel = pluginConfigs.get(0);
        Plugin plugin = new Plugin();
        plugin.setId(pluginConfigModel.getId());
        plugin.setVersion(pluginConfigModel.getVersion());
        plugin.setName(pluginConfigModel.getName());
        plugin.setFileName(objectWriteResponse.object());
        plugin.setStatus(autoActivate ? "enabled" : "disabled");
        if(pluginConfigModel.getIdeaVersion() != null){
            plugin.setUntilBuild(pluginConfigModel.getIdeaVersion().getUntilBuild());
            plugin.setSinceBuild(pluginConfigModel.getIdeaVersion().getSinceBuild());
        }
        pluginMapper.insertOrUpdate(plugin);

        PluginConfig pluginConfig = new PluginConfig();
        pluginConfig.setId(pluginConfigModel.getId());
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(pluginConfigModel);
        pluginConfig.setPluginConfig(json);
        pluginConfigMapper.insertOrUpdate(pluginConfig);

        return new PluginUploadResponseDTO(plugin.getId(), plugin.getName(), plugin.getVersion(), plugin.getStatus());
    }

    @Override
    public PluginDetailDTO getPluginDetail(String pluginId) {
        // 查询插件基本信息
        Plugin plugin = pluginMapper.selectById(pluginId);
        if (plugin == null) {
            throw new BusinessException(ErrorCode.PLUGIN_NOT_FOUND, "插件不存在");
        }

        // 查询插件配置信息
        PluginConfig pluginConfig = pluginConfigMapper.selectById(pluginId);
        
        // 构建详情DTO
        Map<String, Object> configMap = null;
        if (pluginConfig != null) {
            try {
                configMap = new ObjectMapper().readValue(pluginConfig.getPluginConfig(), Map.class);
            } catch (JsonProcessingException e) {
                throw new BusinessException(ErrorCode.PLUGIN_CONFIG_PARSE_ERROR, "插件配置解析失败");
            }
        }
        
        return new PluginDetailDTO(
            plugin.getId(),
            plugin.getName(),
            plugin.getVersion(),
            null, // developer - 暂不支持
            null, // email - 暂不支持
            plugin.getStatus(),
            null, // installTime - 暂不支持
            null, // updateTime - 暂不支持
            plugin.getSinceBuild() + "-" + plugin.getUntilBuild(), // compatibleVersion
            plugin.getDescription(),
            0, // size - 暂不支持
            List.of(), // dependencies - 暂不支持
            List.of(), // extensionPoints - 暂不支持
            configMap
        );
    }

    @Override
    public PluginStatusResponseDTO updatePluginStatus(String pluginId, PluginStatusDTO statusDTO) {
        // 查询插件是否存在
        Plugin plugin = pluginMapper.selectById(pluginId);
        if (plugin == null) {
            throw new BusinessException(ErrorCode.PLUGIN_NOT_FOUND, "插件不存在");
        }

        // 验证状态是否有效
        String newStatus = statusDTO.status();
        if (!isValidStatus(newStatus)) {
            throw new BusinessException(ErrorCode.PLUGIN_STATUS_INVALID, "插件状态只能是enabled或disabled");
        }

        // 更新状态
        plugin.setStatus(newStatus);
        pluginMapper.updateById(plugin);

        // 返回更新后的状态
        return new PluginStatusResponseDTO(plugin.getId(), plugin.getStatus());
    }

    @SneakyThrows
    @Override
    public void deletePlugin(String pluginId, boolean force) {
        // 查询插件是否存在
        Plugin plugin = pluginMapper.selectById(pluginId);
        if (plugin == null) {
            throw new BusinessException(ErrorCode.PLUGIN_NOT_FOUND, "插件不存在");
        }

        // 如果不是强制删除且插件状态为启用，则抛出异常
        if (!force && "enabled".equals(plugin.getStatus())) {
            throw new BusinessException(ErrorCode.PLUGIN_ENABLED_CANNOT_DELETE, "启用状态的插件不能删除，请先禁用或使用强制删除");
        }

        try {
            // 删除MinIO中的文件
            minioClient.removeObject(
                RemoveObjectArgs.builder()
                    .bucket(bucketName)
                    .object(plugin.getFileName())
                    .build()
            );
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.PLUGIN_FILE_DELETE_ERROR, "插件文件删除失败：" + e.getMessage());
        }

        // 删除数据库记录
        pluginMapper.deleteById(pluginId);
        pluginConfigMapper.deleteById(pluginId);
    }

    /**
     * 验证插件状态是否有效
     */
    private boolean isValidStatus(String status) {
        return "enabled".equals(status) || "disabled".equals(status);
    }
}
